package teamproject.visualization.gui.behaviors;

import java.awt.AWTEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.media.j3d.Behavior;
import javax.media.j3d.Bounds;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.WakeupOr;

import teamproject.graphEditor.Node;
import teamproject.graphEditor.SortCollectionsToArray;
import teamproject.visualization.gui.SpaceBarProcessor;
import teamproject.visualization.gui.Visualizer;

public class PackageBufferScheduler extends Behavior implements Resettable {

	private ArrayList<PackageBufferBehavior> bufferBehaviors;
	private SpaceBarProcessor sbp;
	private SortCollectionsToArray scta = new SortCollectionsToArray();
	private Node node;

	private int upperTimeBound;
	private int counter = 0;
	private int edgeId = -2;
	private int numberOfPacketsToBeDisplayedOld;
	private int numberOfPacketsToBeDisplayed;
	private float dataValue;

	private WakeupCriterion[] warray;
	private WakeupOr criterion;
	private WakeupOnAWTEvent wakeupevent;
	private WakeupCriterion wakeupcriterion;
	private AWTEvent[] events;

	public PackageBufferScheduler(
			ArrayList<PackageBufferBehavior> bufferBehaviors, Node node,
			int upperTimeBound, Bounds bounds, int edgeId) {
		this.bufferBehaviors = bufferBehaviors;
		this.node = node;
		this.upperTimeBound = upperTimeBound;
		this.sbp = new SpaceBarProcessor();
		setSchedulingBounds(bounds);
		this.setEdgeId(edgeId);
		scta.sortPackageBufferBehaviors(this.bufferBehaviors);
	}

	private void doProcess() {
		if (!sbp.hasStopped()) {
			if (counter < upperTimeBound) {
				dataValue = node.getDataValue((edgeId + 1), counter);
				numberOfPacketsToBeDisplayed = (int) (dataValue * Visualizer.PACKAGESCALE);
				if (numberOfPacketsToBeDisplayedOld
						- numberOfPacketsToBeDisplayed != 0) {
					if (numberOfPacketsToBeDisplayedOld
							- numberOfPacketsToBeDisplayed > 0) {
						for (int i = numberOfPacketsToBeDisplayed; i <= numberOfPacketsToBeDisplayedOld; i++) {
							bufferBehaviors.get(i).setDisplayed(false);
						}
					} else {
						for (int i = numberOfPacketsToBeDisplayedOld; i <= numberOfPacketsToBeDisplayed; i++) {
							bufferBehaviors.get(i).setDisplayed(true);
							bufferBehaviors.get(i).doProcess();
						}
					}
				}
				numberOfPacketsToBeDisplayedOld = numberOfPacketsToBeDisplayed;
			}
			counter++;
		}
	}

	public int getEdgeId() {
		return edgeId;
	}

	public int getId() {
		return node.getId();
	}

	@Override
	public void initialize() {
		warray = new WakeupCriterion[2];

		warray[0] = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
		warray[1] = new WakeupOnElapsedFrames(Visualizer.FRAMECOUNT
				* Visualizer.SPEEDFACTOR);

		criterion = new WakeupOr(warray);

		wakeupOn(criterion);
	}

	@Override
	public void processStimulus(Enumeration criteria) {
		while (criteria.hasMoreElements()) {
			wakeupcriterion = (WakeupCriterion) criteria.nextElement();
			if (wakeupcriterion instanceof WakeupOnAWTEvent) {
				wakeupevent = (WakeupOnAWTEvent) wakeupcriterion;
				events = wakeupevent.getAWTEvent();
				sbp.processAWTEvents(events);
			} else if (wakeupcriterion instanceof WakeupOnElapsedFrames) {
				doProcess();
			}
		}
		wakeupOn(criterion);
	}

	@Override
	public void reset() {
		counter = 0;
	}

	public void setEdgeId(int edgeId) {
		this.edgeId = edgeId;
	}
}
